前幾天我們已經完成:
HTML
↓
Servlet
↓
JSP
也學會了:
GET
POST
但現在我們的系統還有一個問題。
假設今天有一個醫療資訊系統:
登入
↓
病患列表
↓
病患詳細資料
↓
新增病患
系統怎麼知道:
「這個人剛剛已經登入過了?」
這時候就需要一個很重要的東西:
Session。
⸻
一、為什麼需要 Session?
HTTP 本身是「無狀態」的。
簡單來說,每一次瀏覽器向伺服器發送 Request,伺服器都可以把它視為一次獨立的請求。
例如:
第一次 Request
→ 登入
第二次 Request
→ 查看病患列表
第三次 Request
→ 查看病患詳細資料
如果沒有額外機制,伺服器不會單純因為這三次 Request 來自同一個瀏覽器,就自動知道:
「這是剛剛登入的同一個人。」
所以 Web 應用程式需要一種方式,把多次 Request 關聯起來。
這就是 Session 的用途。(Jakarta EE)
⸻
二、Session 可以想成什麼?
如果要用很簡單的方式理解:
Session 就像系統暫時幫使用者建立的一個「小櫃子」。
例如:
Session
┌──────────────────┐
│ username:小明 │
│ role:doctor │
│ login:true │
└──────────────────┘
只要這個 Session 還有效,其他 Servlet 就可以取得裡面的資料。
例如:
登入 Servlet
↓
建立 Session
↓
儲存 username
↓
病患列表 Servlet
↓
取得 username
這樣系統就能知道:
「小明已經登入了。」
⸻
三、建立 Session
在 Servlet 裡,可以使用:
HttpSession session = request.getSession();
首先要 import:
import jakarta.servlet.http.HttpSession;
完整一點:
protected void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
HttpSession session = request.getSession();
}
getSession() 可以取得目前 Request 對應的 Session;如果目前沒有 Session,這個方法會建立一個新的 Session。(Jakarta EE)
⸻
四、把資料放進 Session
假設我們登入成功之後取得:
String username = "小明";
我們可以:
HttpSession session = request.getSession();
session.setAttribute("username", username);
這就像把資料放進 Session 的「小櫃子」。
可以想成:
Session
↓
username
↓
小明
⸻
五、從 Session 取得資料
如果下一個 Servlet 想知道目前登入的人是誰:
HttpSession session = request.getSession();
String username =
(String) session.getAttribute("username");
如果之前存的是:
小明
現在取得的:
username
就會是:
小明
⸻
六、把它做成登入流程
現在來做一個簡單的登入系統。
假設我們有:
帳號:admin
密碼:1234
HTML:
⸻
七、LoginServlet
建立:
LoginServlet.java
程式:
package MyCode;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
String username =
request.getParameter("username");
String password =
request.getParameter("password");
if ("admin".equals(username)
&& "1234".equals(password)) {
HttpSession session = request.getSession();
session.setAttribute("username", username);
response.sendRedirect("home.jsp");
} else {
response.getWriter()
.println("帳號或密碼錯誤");
}
}
}
這裡最重要的是:
HttpSession session = request.getSession();
session.setAttribute("username", username);
登入成功之後:
Session
┌──────────────────┐
│ username:admin │
└──────────────────┘
系統就可以在後面的 Request 中辨認這個 Session。
⸻
八、JSP 也可以取得 Session
假設登入成功後進入:
home.jsp
我們可以直接顯示:
如果登入的是:
admin
就會顯示:
醫療資訊系統
歡迎,admin
這時候就開始有「登入系統」的感覺了。
⸻
九、為什麼 Session 很適合登入功能?
想像一下,如果沒有 Session。
使用者登入:
帳號:admin
密碼:1234
登入成功。
接著點擊:
病患列表
伺服器又收到一個新的 Request。
如果沒有 Session,系統就很難知道:
「這個人到底有沒有登入?」
但有 Session 之後:
登入
↓
建立 Session
↓
username = admin
↓
查看病患列表
↓
讀取 Session
↓
確認 admin
這就是 Session 最常見的用途之一。
⸻
十、Session 和 Request 有什麼不同?
這個很重要。
前面我們學過:
request.setAttribute()
現在又學:
session.setAttribute()
它們到底差在哪?
可以先這樣記:
Request Session
保存範圍 一次 Request 多次 Request
常見用途 傳資料給 JSP 保存登入狀態
生命週期 通常較短 可跨多個頁面
範例 病患資料 登入帳號
例如:
request.setAttribute("name", name);
通常是:
Servlet
↓
JSP
把資料傳過去。
而:
session.setAttribute("username", username);
則是:
登入
↓
Session
↓
其他頁面
讓資料可以跨多次 Request 使用。
⸻
十一、Session 不是永久存在
Session 並不是永久保存的。
例如使用者離開一段時間,Session 可能因為逾時而失效。
Jakarta Servlet 提供:
session.getMaxInactiveInterval();
可以取得 Session 的最大閒置時間;也可以使用:
session.setMaxInactiveInterval(...)
設定閒置時間。(Jakarta EE)
所以:
Session 適合保存「目前這次使用者操作」需要的狀態,而不是拿來永久儲存病患資料。
真正需要永久保存的資料,還是應該放進:
MySQL
這一點對我們的醫療資訊系統尤其重要。
⸻
十二、Session 和 Cookie
你可能會開始看到另一個名詞:
Cookie。
兩個東西不是完全一樣。
簡單理解:
Cookie
↓
瀏覽器端保存的一些資訊
而:
Session
↓
伺服器端管理的使用者 Session
Servlet 容器通常會透過 Session ID 來辨識同一個 Session;最常見的 Session Cookie 名稱是:
JSESSIONID
Jakarta Servlet 規格也指出,Cookie 是最常用的 Session Tracking 機制。(Jakarta EE)
所以你可以先記成:
Browser
│
│ JSESSIONID
↓
Server
│
↓
HttpSession
│
├── username
├── login status
└── 其他暫存資訊
⸻
十三、放回我們的醫療資訊小系統
現在我們可以開始設計真正的系統:
登入頁面
↓
LoginServlet
↓
驗證帳號密碼
↓
建立 HttpSession
↓
┌──────┴──────┐
↓ ↓
病患列表 新增病患
↓ ↓
PatientServlet
↓ ↓
MySQL
這樣就開始越來越接近我們一開始想做的系統了。
⸻
十四、今天學到什麼?
今天我們學到:
① HTTP 是無狀態的
不同 Request 本身不會自動知道彼此的關係。
② Session 可以保存使用者狀態
HttpSession session = request.getSession();
③ 可以把資料放進 Session
session.setAttribute("username", username);
④ 可以從 Session 取出資料
session.getAttribute("username");
⑤ Session 很常用在登入功能
例如:
登入成功
↓
建立 Session
↓
記住使用者
↓
進入其他頁面
⸻
今日小結
做到今天,我們的醫療資訊小系統又多了一個重要能力:
記住使用者。
前幾天我們解決的是:
「怎麼把資料送給 Java?」
今天解決的是:
「Java 怎麼知道這幾次操作是同一個人?」
答案就是:
Session。
目前系統的學習路線也越來越完整:
HTML
↓
CSS
↓
Servlet
↓
JSP
↓
GET / POST
↓
Session
而下一個非常重要的階段就是:
MySQL 資料庫。
因為 Session 只能暫時保存使用者狀態,真正的病患資料不能只放在 Session 裡。
下一篇,我們就要開始建立:
medical_system
以及第一張:
patient
資料表。
Day 14 完成 ✅